#pragma once

#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <vector>

#include "current_thread.h"
#include "noncopyable.h"
#include "timestamp.h"

class Channel;
class Poller;

// 时间循环类，提供两个子类， Channel     Poller(可以这里看成Epoll的封装)
class EventLoop : noncopyable{
  public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开启事件循环
    void loop();
    // 退出事件循环
    void quit();

    Timestamp poll_return_time() const { return poll_return_time_; }

    // 在当前loop执行cb
    void run_in_loop(Functor cb);
    // 把cb放入队列中，唤醒loop所在的线程，执行cb
    void queue_in_loop(Functor cb);

    // 用来唤醒loop所在的线程
    void wakeup();

    // EventLoop的方法 => Poller的方法
    void update_channel(Channel *channel);
    void remove_channel(Channel *channel);
    bool has_channel(Channel *channel);

    // 判断EventLoop对象是否在自己的线程里面
    bool is_in_loop_thread() const { return thread_id_ == current_thread::tid(); }

  private:
    void handle_read();         // wake up
    void do_pending_functors(); // 执行回调

    using ChannelList = std::vector<Channel *>;

    std::atomic_bool looping_; // 原子操作，通过CAS实现
    std::atomic_bool quit_;    // 表示退出loop循环

    const pid_t thread_id_; // 记录loop所在的线程id

    Timestamp poll_return_time_; // poller返回发生事件的channels 的时间点
    std::unique_ptr<Poller> poller_;

    int wakeup_fd_; // 主要作用，当main_loop获取一个新用户的channel,通过轮询算法选择一个subloop,通过该成员唤醒subloop处理
    std::unique_ptr<Channel> wakeup_channel_;

    ChannelList active_channels_;

    std::atomic_bool call_pending_functors_; // 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pending_functors_;  // 存储loop需要执行的所有的回调操作
    std::mutex mutex_;                       // 互斥锁，用来保护上面vector容器的线程安全操作
};